package pro.lepers.portfolio.view.contents.portfolio.content {
	import pro.lepers.portfolio.Consts;
	import pro.lepers.portfolio.core.master;
	import pro.lepers.portfolio.event.MasterModelEvent;
	import pro.lepers.portfolio.view.contents.portfolio.data.contents.AbstractContentData;
	import pro.lepers.portfolio.view.contents.portfolio.data.contents.VideoContentData;

	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.utils.clearTimeout;
	import flash.utils.setTimeout;

	/**
	 * @author Pierre Lepers
	 */
	public class VideoContent extends ThumbContent {

		
		
		public function VideoContent (pcData : AbstractContentData ) {
			super( pcData );
			
			
			//addEventListener( Event.ADDED_TO_STAGE, onAdded );
			addEventListener( Event.REMOVED_FROM_STAGE, onRemoved );

			_build( );
		}

		
		private function onRemoved (event : Event) : void {
			_killMoveTimer();
		}

		
		override public function dispose () : void {
			trace( "pro.lepers.portfolio.view.contents.portfolio.content.VideoContent - dispose : " );
			super.dispose( );
			if( _tplayer.parent )
				removeChild( _tplayer );
			if( _player.parent )
				removeChild( _player );
			_player.dispose( );
			_player = null;
			_tplayer.dispose( );
			_tplayer = null;
			
			clearMaster();
		}

		override public function shown (  ) : void {
			super.shown( );
			_updateSize();
			
			callRender( true );
			
			if( numChildren == 0 )	_focusChange( );
		}

		
		override public function hidded () : void {
			super.hidded( );
			callRender( false );
			_tplayer.stop( );
			_player.stop( );
		}

		
		override public function setSize (w : int, h : int) : void {
			super.setSize( w, h );
			_updateSize();
		}

		private function _updateSize () : void {
			if( _player ) {
				_player.container.x = -( _overScale - 1 ) * _width / 2;
				_player.container.y = -( _overScale - 1 ) * _height / 2;
				_player.setSize( _width * _overScale, _height * _overScale );
			}
			
			if( _tplayer ) {
				_tplayer.container.x = ( _overScale - 1 ) * _width / 2;
				_tplayer.container.y = ( _overScale - 1 ) * _height / 2;
				_tplayer.setSize( _width * _overScale, _height * _overScale );
			}
		}

		
		
		override public function set highQuality (highQuality : Boolean) : void {
			super.highQuality = highQuality;
			//			if( _player ) 
			//				_player.video.smoothing = highQuality;
			if( _tplayer ) 
				_tplayer.video.smoothing = highQuality;
		}
		
		

		
		override public function set flyOver (flyOver : Boolean) : void {
			super.flyOver = flyOver;
			if( flyOver ) {
				master.addEventListener( MasterModelEvent.SCALE_CHANGE, masterScaleChange );
				master.addEventListener( MasterModelEvent.UP_SCALED, clearMaster );
			} else
				mouseMove( null );
		}

		private function clearMaster (event : MasterModelEvent = null ) : void {
			master.removeEventListener( MasterModelEvent.SCALE_CHANGE, masterScaleChange );
			master.removeEventListener( MasterModelEvent.UP_SCALED, clearMaster );
		}

		private function masterScaleChange (event : MasterModelEvent) : void {
			overScale = 1 + ( 1 - master.scaleProgress ) * _overScaleD;
		}

		
		private function _focusChange () : void {
			
			if( _focused ) {
				_player.play( );
				addChild( _player );
	
				_tplayer.stop( );
				if( _tplayer.parent )
					removeChild( _tplayer );
			} else {
				_tplayer.play( );
				addChild( _tplayer );
	
				_player.stop( );
				if( _player.parent )
					removeChild( _player );
				
				clearMaster();
			}
		}

		override public function focused () : void {
			super.focused( );
			_focusChange( );
			_initMoveTimer( );
		}

		
		override public function unfocused () : void {
			super.unfocused( );
			_killMoveTimer( );
			_focusChange( );
		}

		
		override public function unfocus () : void {
			super.unfocus( );
			_killMoveTimer( );
		}

		private function _build () : void {
			_player = new Player( videoData.flvUrl );
			_tplayer = new Player( videoData.thumbUrl );
			
			_player.video.smoothing = false;
			_tplayer.video.smoothing = highQuality;
			_tplayer.video.deblocking = 1;
			_tplayer.control.height = 4;
		}

		private function get videoData () : VideoContentData {
			return _contentData as VideoContentData;
		}

		//_____________________________________________________________________________
		//																	IDLE SYSTEM
		private function _initMoveTimer () : void {
			if( stage )
				addedForTimer( null );
			else
				addEventListener( Event.ADDED_TO_STAGE, addedForTimer );
		}

		private function addedForTimer (event : Event) : void {
			removeEventListener( Event.ADDED_TO_STAGE, addedForTimer );
			stage.addEventListener( MouseEvent.MOUSE_MOVE, mouseMove );
			clearTimeout( _moveTimeout );
			_moveTimeout = setTimeout( idle, Consts.SCALE_IDLE_DELAY*1000 );
		}

		private function _killMoveTimer () : void {
			clearTimeout( _moveTimeout );
			stage.removeEventListener( MouseEvent.MOUSE_MOVE, mouseMove );
			removeEventListener( Event.ADDED_TO_STAGE, addedForTimer );
		}

		private function mouseMove (event : MouseEvent) : void {
			clearTimeout( _moveTimeout );
			_moveTimeout = setTimeout( idle, Consts.SCALE_IDLE_DELAY*1000 );
			
		}

		private function idle () : void {
			flyOver = true;
		}

		
		//_____________________________________________________________________________
		//																	  OverScale
		
		
		public function get overScale () : Number {
			return _overScale;
		}
		
		public function set overScale (overScale : Number) : void {
			_overScale = overScale;
			_updateSize();
		}

		private var _overScale : Number = 1;
		private var _overScaleD : Number = .2;

		
		
		private var _player : Player;

		private var _tplayer : Player;

		private var _moveTimeout : int;
	}
}

import fr.digitas.flowearth.event.BoolEvent;
import fr.digitas.flowearth.event.NumberEvent;

import pro.lepers.portfolio.view.contents.portfolio.misc.ProxyClient;
import pro.lepers.portfolio.view.contents.portfolio.misc.VideoControl;
import pro.lepers.portfolio.view.contents.portfolio.misc.VideoControl_FC;

import flash.display.Sprite;
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;

class Player extends Sprite {

	public var video : Video;

	public var container : Sprite;
	
	public var control : VideoControl;
	
	public static const BUFFER : String = "__buffer__";

	private var proxy : ProxyClient;

	public function Player ( url : String ) {
		_url = url;
		_build( );
		
		addEventListener( Event.ADDED_TO_STAGE, onAdded );
		addEventListener( Event.REMOVED_FROM_STAGE, onRemoved );
	}

	private function onAdded ( e : Event ) : void {
		addEventListener( Event.ENTER_FRAME, _oef );
	}

	private function onRemoved ( e : Event ) : void {
		removeEventListener( Event.ENTER_FRAME, _oef );
	}

	private function _oef (event : Event) : void {
		if( ! control.seek && _ns && !isNaN( _duration ) ) {
			control.seekBar.progress = _ns.time / _duration;
		}
	}

	public function play () : void {
		if( _ns ) {
			if ( !_connected )
				_ns.play( _url );
			else
				_ns.resume( );
		}
		_connected = true;
	}

	public function stop () : void {
		if( !_ns ) _connected = false;
		else _ns.pause( );
	}

	public function setSize (w : int, h : int) : void {
		video.width = w;
		video.height = w * 720 / 1280;
		
		control.y = video.height + 2;
		control.setSize( w - 4 );
	}

	
	private function _build () : void {
		container = new Sprite();
		addChild( container );
		
		video = new Video( );
		video.smoothing = true;
		container.addChild( video );
		
		_nc = new NetConnection( );
		_nc.addEventListener( NetStatusEvent.NET_STATUS, ncStatus, false, 0, true );
		_nc.connect( null );
		
		control = new VideoControl_FC( );
		container.addChild( control );
		
		control.addEventListener( VideoControl.SEEK, onSeek );
	}

	private function onSeek (event : NumberEvent ) : void {
		_ns.seek( event.value * _duration );
	}

	
	private function ncStatus ( e : NetStatusEvent ) : void {
		if( e.info.code == "NetConnection.Connect.Success" )	
			connectStream( );
		if( e.info.level == "error" ) 	
			error( e.info.code );
	}

	
	private function connectStream () : void {
		_ns = new NetStream( _nc );
		_ns.client = proxy = new ProxyClient( this );
		_ns.bufferTime = 10;
		_ns.addEventListener( NetStatusEvent.NET_STATUS, nsStatus );
		video.attachNetStream( _ns );
		_ns.pause( );
		
		if( _connected ) play( );
	}

	private function nsStatus ( e : NetStatusEvent ) : void {
			
		//			Logger.log( "bi.media.player.loader.FlvLoader - nsStatus -- ", e.info.code );

		if( e.info.level == "error" && e.info.code != "NetStream.Seek.InvalidTime" ) error( e.info.code + " - " + _url );
			
			
		//			dispatchEvent( new StatusEvent( MediaPlayer.STATUS , false, false, e.info.code, e.info.level ) );

		switch (e.info.code) {
			case "NetStream.Play.Stop":
				playComplete( );
				break;
			case "NetStream.Play.Start":
				break;
			case "NetStream.Pause.Notify":
				buffer( false );
				break;
			case "NetStream.Unpause.Notify":
				break;
			case "NetStream.Seek.Notify":
				break;
			case "NetStream.Buffer.Empty":
				buffer( true );
				break;
			case "NetStream.Buffer.Full":
				buffer( false );
				break;
			case "NetStream.Buffer.Flush":
				//				_buffFlushed = true;
				//				_checkLoadComplete( );
				buffer( false );
				break;
		}
	}

	public function onMetaData ( infoObj : Object ) : void {
		_duration = infoObj.duration;	
	}

	private var _duration : Number;

	private function playComplete () : void {
	}

	
	private function buffer ( flag : Boolean) : void {
		dispatchEvent( new BoolEvent( BUFFER, flag ) );
	}

	
	
	public function dispose () : void {
		
		if( _nc ) {
			_nc.removeEventListener( NetStatusEvent.NET_STATUS, ncStatus, false );
			_nc.close( );
			_nc = null;
		}
		
		if( _ns ) {
			_ns.removeEventListener( NetStatusEvent.NET_STATUS, nsStatus );
			_ns.close( );
			_ns = null;
		}
		
		if( video ) {
			video.clear( );
			container.removeChild( video );
			video = null;
		}
		
		if( control ) {
			control.removeEventListener( VideoControl.SEEK, onSeek );
			container.removeChild( control );
			control = null;
		}
	}

	private function error ( text : String ) : void {
		throw new Error( "VideoStream error : " + text );
	}	

	private var _url : String;

	//	private var _play : Boolean = false;

	private var _connected : Boolean = false;

	private var _nc : NetConnection;

	private var _ns : NetStream;
	


//	private var _ncConnect
}
